Skip to content

feat(normalize): render post attachment zone in convertPost - #18

Merged
mazhe-nerd merged 4 commits into
larksuite:mainfrom
yjhcjykwbk-jlsec:feat/post-attachment-zone
Aug 31, 2026
Merged

feat(normalize): render post attachment zone in convertPost#18
mazhe-nerd merged 4 commits into
larksuite:mainfrom
yjhcjykwbk-jlsec:feat/post-attachment-zone

Conversation

@yjhcjykwbk-jlsec

Copy link
Copy Markdown

Summary

The rich-text attachment zone (top-level files array on a post message) was ignored by convertPost: only the locale document (title/content/content_v2) was flattened and scanned for resources, so attachments attached to a rich-text message were invisible to channel consumers (agents/CLIs).

This PR makes the attachment zone visible and downloadable:

  • src/normalize/converters/post.ts
    • topLevelAttachments(): extract the top-level files: [{file_key, file_name, is_folder}] array
    • render attachment-zone entries as <file key="..." name="..."/> / <folder key="..." name="..."/> lines after the body, matching the standalone file/folder converters
    • surface attachment-zone files as ResourceDescriptor(type: 'file') so they are downloadable; folders stay tag-only (mirrors the standalone folder converter's resources: [])
  • src/normalize/__tests__/converters.test.ts: two new tests — rendering + resource extraction, and empty files array tolerance

Wire shape

{
  "zh_cn": { "title": "报告", "content": [...] },
  "files": [
    { "file_key": "file_a", "file_name": "report.pdf" },
    { "file_key": "dir_1", "file_name": "assets", "is_folder": true }
  ]
}

renders as:

**报告**
正文
<file key="file_a" name="report.pdf"/>
<folder key="dir_1" name="assets"/>

with resources: [{type: 'file', fileKey: 'file_a', fileName: 'report.pdf'}].

Test

pnpm test   # 548 passed
pnpm typecheck  # clean

The rich-text attachment zone (top-level files array) was ignored by the
post converter: only the locale document (title/content) was flattened
and scanned for resources, so attachments attached to a rich-text message
were invisible to channel consumers.

- render attachment-zone files as <file key=... name=.../> lines and
  is_folder entries as <folder .../> lines, matching the standalone
  file/folder converters
- surface attachment-zone files as ResourceDescriptor(type=file) so they
  are downloadable; folders remain tag-only like the folder converter
- cover with tests: rendering + resource extraction, empty files array
@yjhcjykwbk-jlsec
yjhcjykwbk-jlsec force-pushed the feat/post-attachment-zone branch from e4d7480 to aa84321 Compare August 31, 2026 09:30
…lues

Follow-up fixes on top of the attachment-zone support, covering paths the
original change left untested:

- Read the attachment zone before the locale guard. `files` is a sibling of
  the locale documents, not part of one, so a post whose locale document
  cannot be unwrapped was silently dropping its attachments entirely.
- Normalize entries in `topLevelAttachments` instead of casting the raw wire
  record. A non-string `file_name` reached `escapeAttr` and threw, which
  `dispatchConvert` traps by falling back to the unknown-message converter —
  replacing the entire message, body and all, with a placeholder.
- Compare `is_folder` against `true` rather than testing truthiness, so a
  string `"false"` cannot hide a real, downloadable file behind a `<folder/>`
  tag and drop it from `resources`.
- Escape the key as well as the name when rendering tags, matching how these
  tags are produced elsewhere.

The narrowed `PostAttachment` type now states what the extractor actually
guarantees, which removes the redundant empty-key check and the duplicated
attribute construction in the render loop.

Adds regression tests for each path, plus an ordering assertion the existing
`toContain` checks could not make.
…nvariant

Addresses review follow-ups on the attachment-zone change:

- The rich-text placeholder string was repeated at three exits; name it once
  so the three agree by construction.
- Add a test for the invariant the attachment zone relies on but nothing
  covered: attachments are appended to the body's own resources rather than
  replacing them, so an image and a media element still survive alongside an
  attachment-zone file.
- Drop a duplicated restatement of the file-vs-folder rule; it is already
  documented where the rule is enforced.
Mechanical only: biome wraps the long toContainEqual argument. No assertion
or behavior change.
@mazhe-nerd
mazhe-nerd merged commit 073e97d into larksuite:main Aug 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants